//
//  SleepStagingV2.m
//  sr01sdkProject
//
//  Created by Linktop on 2022/8/16.
//

#import "SleepStagingV2.h"
#import "NSDictionary+SleepUsed.h"
#import "SleepStagingUtils.h"
#import "sleep_api.h"
#include "csem_api.h"



@implementation SleepStagingV2
{
    NSDateFormatter *_formatter;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        _formatter = [[NSDateFormatter alloc]init];
        _formatter.dateFormat = @"yyyy年MM月dd日 ah:mm:ss";
    }
    return self;
}

+(NSString *)versionTag
{
    return @"c47629"; // 老杨c的Git log
}
+(NSString *)buildDate
{
    return @"2024-12-26";
}


-(SleepStagingResultV2 *)findSleepDataByLib:(NSMutableArray <SleepSourceData *> *)originData
{
    
    if (!originData.count){
        return nil;
    }

    originData = [self dumplicateTimeFlter:originData]; // 去重
    NSUInteger count = originData.count;
    
    smp_hr_t *dlist = (smp_hr_t *)malloc(sizeof(smp_hr_t) * count);
    if (dlist == NULL) {
        return nil; // 内存分配失败
    }
    // 转换原始数据
    for (size_t i = 0; i < count; i++) {
        
        SleepSourceData *dbObj = originData[i];
        smp_hr_t *dst = dlist + i;
        
        dst->ts = dbObj.time.doubleValue * 1000;//毫秒 (uint64_t)cJSON_GetObjectItem(each, "ts")->valuedouble;
        dst->motion =  dbObj.soprtTimes.unsignedShortValue;
        
        dst->rate = dbObj.deviceModifyHeartRate.unsignedShortValue ;
        dst->hrv = dbObj.hrv.intValue > 0 ? dbObj.hrv.unsignedIntValue : 1 ;
        dst->steps = dbObj.steps.unsignedIntValue;
        
    }
    
    sleep_root *output = NULL;
    v3_calc(dlist, count, &output); // 计算睡眠
    
    if (!output) {
        DebugNSLog(@"V3 没有睡眠!");
        free(dlist);
        return nil;
    }
    
    SleepStagingResultV2 *allSleepHead = [[SleepStagingResultV2 alloc]init];
    allSleepHead.stagingDataList = [NSMutableArray new];
    
    for (size_t i = 0; i < output->count; i++) {
        
        activity_summary_t *as = output->summaries + i; // 睡眠

        StagingDataV2 *sleepObj = [[StagingDataV2 alloc]init];
        sleepObj.startTime = as->begin / 1000; // 毫秒转回秒
        sleepObj.endTime = as->end / 1000;
        sleepObj.averageHr = as->avg_hr;
//      printf("stage#%zu, %lu, %lu, %f\n", i, as->begin, as->end, as->avg_hr); // 睡眠区间时间
        sleepObj.ousideStagingList = [NSMutableArray new];
        
      for (size_t j = 0; j < as->cnt_acts; j++) {
          each_activity_t *ea = as->act_list + j; // 分期遍历
          
          StagingSubObj *stagingSubObj = [StagingSubObj new];
          stagingSubObj.list = [NSMutableArray new];
          
          // 兼容V2的type定义
          stagingSubObj.type = [self transType:ea->type];
          
          StagingListObj *beginObj = [[StagingListObj alloc]init];
          beginObj.time = @(ea->begin / 1000);
          
          StagingListObj *endObj = [[StagingListObj alloc]init];
          endObj.time = @(ea->end /  1000);
          
          [stagingSubObj.list addObject:beginObj];
          [stagingSubObj.list addObject:endObj];
          
          [sleepObj.ousideStagingList addObject:stagingSubObj];
//        output_stg(ea->begin, ea->end, ea->type); // 单个分期时间
      }
        [allSleepHead.stagingDataList addObject:sleepObj]; // 睡眠加入数组
    }
    
    free_activities(output);
    free(dlist);
    
    return allSleepHead;
}


// 用于 csXm设备的睡眠计算
-(SleepStagingResultV2 *)findCMSleepDataByLib:(NSMutableArray <SleepSourceData *> *)originData SlpAssistData:(NSMutableArray <SleepCmAstncData *> *)sleepAstDataArray
{
    if (!originData.count || !sleepAstDataArray.count) {
        return nil;
    }

    originData = [self dumplicateTimeFlter:originData]; // 去重
    NSUInteger count = originData.count;
    
    smp_hr_t *dlist = (smp_hr_t *)malloc(sizeof(smp_hr_t) * count);
    if (dlist == NULL) {
        return nil; // 内存分配失败
    }
    // 转换原始数据
    for (size_t i = 0; i < count; i++) {
        
        SleepSourceData *dbObj = originData[i];
        smp_hr_t *dst = dlist + i;
        
        dst->ts = dbObj.time.doubleValue * 1000;//毫秒 (uint64_t)cJSON_GetObjectItem(each, "ts")->valuedouble;
        dst->motion =  dbObj.soprtTimes.unsignedShortValue;
        
        dst->rate = dbObj.deviceModifyHeartRate.unsignedShortValue ;
        dst->hrv = dbObj.hrv.intValue > 0 ? dbObj.hrv.unsignedIntValue : 1 ;
        dst->steps = dbObj.steps.unsignedIntValue;
        
    }
    
    sleepAstDataArray = [self sleepSRCDumplicateTimeFlter:sleepAstDataArray];// 去重, 升序
    NSUInteger sleepCount = sleepAstDataArray.count;
    
    csem_sleep_t *csem_sleep_list = (csem_sleep_t *)malloc(sizeof(csem_sleep_t) * sleepCount);
    if (csem_sleep_list == NULL) {
        return nil; // 内存分配失败
    }
    
    // TODO:睡眠数据转换格式填充
    for (size_t i = 0; i < sleepCount; i++) {
        SleepCmAstncData * sleepAssitObj = sleepAstDataArray[i];
        csem_sleep_t *sleepdst = csem_sleep_list + i;
        sleepdst->ts =  sleepAssitObj.ts.unsignedLongValue * 1000;//毫秒
        sleepdst->type = sleepAssitObj.type.unsignedCharValue;
        sleepdst->awake_order = sleepAssitObj.awake_order.intValue;
        sleepdst->bed_rest_duration = sleepAssitObj.bed_rest_duration.longValue;
    }
    
    sleep_root *output = NULL;
    csem_calc(csem_sleep_list , sleepCount, dlist, count, &output);//csem 计算睡眠
//    v3_calc(dlist, count, &output); // 计算睡眠
    
    if (!output) {
        DebugNSLog(@"csem V4 没有睡眠!");
        free(dlist);
        return nil;
    }
    
    SleepStagingResultV2 *allSleepHead = [[SleepStagingResultV2 alloc]init];
    allSleepHead.stagingDataList = [NSMutableArray new];
    
    for (size_t i = 0; i < output->count; i++) {
        
        activity_summary_t *as = output->summaries + i; // 睡眠

        StagingDataV2 *sleepObj = [[StagingDataV2 alloc]init];
        sleepObj.startTime = as->begin / 1000; // 毫秒转回秒
        sleepObj.endTime = as->end / 1000;
        sleepObj.averageHr = as->avg_hr;
//      printf("stage#%zu, %lu, %lu, %f\n", i, as->begin, as->end, as->avg_hr); // 睡眠区间时间
        sleepObj.ousideStagingList = [NSMutableArray new];
        
      for (size_t j = 0; j < as->cnt_acts; j++) {
          each_activity_t *ea = as->act_list + j; // 分期遍历
          
          StagingSubObj *stagingSubObj = [StagingSubObj new];
          stagingSubObj.list = [NSMutableArray new];
          
          // 兼容V2的type定义
          stagingSubObj.type = [self transType:ea->type];
          
          StagingListObj *beginObj = [[StagingListObj alloc]init];
          beginObj.time = @(ea->begin / 1000);
          
          StagingListObj *endObj = [[StagingListObj alloc]init];
          endObj.time = @(ea->end /  1000);
          
          [stagingSubObj.list addObject:beginObj];
          [stagingSubObj.list addObject:endObj];
          
          [sleepObj.ousideStagingList addObject:stagingSubObj];
//        output_stg(ea->begin, ea->end, ea->type); // 单个分期时间
      }
        [allSleepHead.stagingDataList addObject:sleepObj]; // 睡眠加入数组
    }
    
    free_activities(output);
    free(dlist);
    
    return allSleepHead;
}


// 去重
-(NSMutableArray <SleepSourceData *> *)dumplicateTimeFlter:(NSMutableArray <SleepSourceData *> *)originData {

    NSMutableDictionary <NSNumber * , SleepSourceData *>* filterDict = [NSMutableDictionary new];
    [originData enumerateObjectsUsingBlock:^(SleepSourceData * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        filterDict[obj.time] = obj;
    }];
    
    originData = [NSMutableArray new];
    NSArray<NSNumber *> *keys = filterDict.allKeys;
    for (int i = 0; i < keys.count; i++) {
        
        [originData addObject:filterDict[ keys[i] ] ];
    }
    
    [originData sortUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        
        SleepSourceData *his1 = obj1;
        SleepSourceData *his2 = obj2;
        return [his1.time compare:his2.time]; // 按time升序
    }];
    
    return originData;
}

-(NSMutableArray <SleepCmAstncData *> *)sleepSRCDumplicateTimeFlter:(NSMutableArray <SleepCmAstncData *> *)originData
{

    NSMutableDictionary <NSNumber * , SleepCmAstncData *>* filterDict = [NSMutableDictionary new];
    [originData enumerateObjectsUsingBlock:^(SleepCmAstncData * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        filterDict[obj.ts] = obj;
    }];
    
    originData = [NSMutableArray new];
    NSArray<NSNumber *> *keys = filterDict.allKeys;
    for (int i = 0; i < keys.count; i++) {
        
        [originData addObject:filterDict[ keys[i] ] ];
    }
    
    [originData sortUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        
        SleepCmAstncData *his1 = obj1;
        SleepCmAstncData *his2 = obj2;
        return [his1.ts compare:his2.ts]; // 按time升序
    }];
    
    return originData;
}


-(SleepStagingType)transType:(sleep_types_t)v3Type {
    SleepStagingType resType = WAKE;
  
    switch (v3Type) {
        case ENUM_SLEEP_STAGING_TYPE_NONE:
        {
            resType = NONE;
        }
            break;
        case ENUM_SLEEP_STAGING_TYPE_WAKE:
        {
            resType = WAKE;
        }
            break;
        case ENUM_SLEEP_STAGING_TYPE_NREM1:
        {
            resType = NREM1;
        }
            break;
        case ENUM_SLEEP_STAGING_TYPE_NREM3:
        {
            resType = NREM3;
        }
            break;
        case ENUM_SLEEP_STAGING_TYPE_REM:
        {
            resType = REM;
        }
            break;
        case ENUM_SLEEP_STAGING_TYPE_NAP: // 打盹
        {
            resType = NAP;
        }
            
            
        default:
            break;
    }
    
    return resType;
}




-(NSMutableArray<NSMutableDictionary *> *)readFile
{
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"ztt.txt" ofType:nil];

    
    NSData *data = [NSData dataWithContentsOfFile:filePath];
    NSString *string = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    
    NSArray<NSString *> *lines = [string componentsSeparatedByString:@"\r\n"];
    
    NSMutableArray <NSMutableDictionary *> * res = [NSMutableArray new];
    [lines enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSArray<NSString *> *seps = [obj componentsSeparatedByString:@"\t"];
        if (seps.count >= 3) {
//            DebugNSLog(@"%@ %@ %@", seps[0], seps[1], seps[2]);
            // 时间
            NSDate *date = [_formatter dateFromString:seps[0]];
            NSTimeInterval interval = [date timeIntervalSince1970];
            NSNumber *time = @(interval);
            // hr
            NSNumber *hr = @([seps[1] integerValue]);
            // 运动计数
            NSNumber *sportCount = @([seps[2] integerValue]);
//            DebugNSLog(@" %@ %@ %@", time, hr, sportCount);
            NSMutableDictionary *dict = [NSMutableDictionary new];
            dict[FIRST] = time;
            dict[SECOND] = hr;
            dict[THIRD] = sportCount;
            [res addObject:dict];
        }
       
        
    }];
   
    return res;
}


-(NSString *)TestformatTimeStamp:(NSTimeInterval)timeInterval
{
    
    NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval];
    return [_formatter stringFromDate:date];
}

-(NSMutableArray<NSMutableDictionary *> *)readFileV3FileName:(NSString *)fileName
{
    NSString *filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:nil];

    
    NSData *data = [NSData dataWithContentsOfFile:filePath];
    NSString *string = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    
    NSArray<NSString *> *lines = [string componentsSeparatedByString:@"\r\n"];
    
    NSMutableArray <NSMutableDictionary *> * res = [NSMutableArray new];
    [lines enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSArray<NSString *> *seps = [obj componentsSeparatedByString:@"\t"];
        if (seps.count >= 4) {
//            DebugNSLog(@"%@ %@ %@", seps[0], seps[1], seps[2]);
            // 时间
            NSDate *date = [_formatter dateFromString:seps[0]];
            NSTimeInterval interval = [date timeIntervalSince1970];
            NSNumber *time = @(interval);
            
            NSNumber *isOn = @([seps[1] integerValue]);
            if (isOn.intValue > 0) {
                // hr
                NSNumber *hr = @([seps[3] integerValue]);
                // 运动计数
                NSNumber *sportCount = @([seps[2] integerValue]);
    //            DebugNSLog(@" %@ %@ %@", time, hr, sportCount);
                NSMutableDictionary *dict = [NSMutableDictionary new];
                dict[FIRST] = time;
                dict[SECOND] = hr;
                dict[THIRD] = sportCount;
                [res addObject:dict];
            }
      
        }
       
        
    }];
   
    return res;
}

//

@end
